#include "BlockQueue.hpp"
#include "Task.hpp"
#include <iostream>
#include <vector>
#include <unistd.h>
#include <pthread.h>
#include <ctime>
using std::cout;
using std::endl;
using typeinbp = Task;
using typeofbq = BlockQueue<typeinbp>;

struct ThreadData
{
    ThreadData(const std::string &str = "no_name", typeofbq *pbq = nullptr)
        : _name(str), _pbq(pbq) {}

    std::string _name;
    typeofbq *_pbq;
};

void *producercode(void *args)
{
    ThreadData *ptd = static_cast<ThreadData *>(args);
    while (1)
    {
        int a = rand() % 100;
        usleep(1234);
        int b = rand() % 100;
        typeinbp tmp(a, b);
        // ptd->_pbq->Enqueue(printhello);
        ptd->_pbq->Enqueue(tmp);
        cout << ptd->_name << " product a ques " << tmp.question_to_string() << endl;
        sleep(1);
    }
    delete ptd;
    return nullptr;
}
void *consumercode(void *args)
{
    ThreadData *ptd = static_cast<ThreadData *>(args);
    while (1)
    {
        typeinbp tmp;
        ptd->_pbq->Pop(&tmp);
        // tmp();
        cout << ptd->_name << " get a message: " << tmp.result_to_string() << endl;
    }
    delete ptd;
    return nullptr;
}

void startproducer(std::vector<pthread_t> *ppids, int num, typeofbq *pbq)
{
    for (int i = 1; i <= num; i++)
    {
        std::string name = "producer_" + std::to_string(i);
        ThreadData *ptd = new ThreadData(name, pbq);
        pthread_t pid;
        pthread_create(&pid, nullptr, producercode, (void *)ptd);
        ppids->push_back(pid);
    }
}
void startconsumer(std::vector<pthread_t> *ppids, int num, typeofbq *pbq)
{
    for (int i = 1; i <= num; i++)
    {
        std::string name = "consumer_" + std::to_string(i);
        ThreadData *ptd = new ThreadData(name, pbq);
        pthread_t pid;
        pthread_create(&pid, nullptr, consumercode, (void *)ptd);
        ppids->push_back(pid);
    }
}
void waitall(std::vector<pthread_t> &pids)
{
    for (auto &pid : pids)
    {
        pthread_join(pid, nullptr);
    }
}
int main()
{
    srand(time(nullptr));
    std::vector<pthread_t> pids;
    typeofbq bq(5);
    startproducer(&pids, 3, &bq);
    startconsumer(&pids, 4, &bq);
    waitall(pids);

    return 0;
}